
format ELF64 executable 3
entry start

include 'util/import64.inc'

interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libdl.so.2'
import dlopen,dlsym

segment readable executable

ENEIDA_UTIL_INCLUDE = 'CODE'
include 'util/util_amath.inc'
include 'util/util_vmath.inc'
include 'util/util_window.inc'
include 'util/util_openctm.inc'
include 'util/util_stb_image.inc'

;-------------------------------------------------------------------------------
macro rand_f32 {
    call [rand]
    cvtsi2ss xmm0,eax
    mov eax,RAND_MAX
    cvtsi2ss xmm1,eax
    divss xmm0,xmm1
}
macro rand_v3_f32 {
    call [rand]
    movd xmm0,eax
    call [rand]
    movd xmm1,eax
    pshufd xmm1,xmm1,11110011b
    call [rand]
    movd xmm2,eax
    pshufd xmm2,xmm2,11001111b
    pxor xmm0,xmm1
    pxor xmm0,xmm2
    cvtdq2ps xmm0,xmm0
    mov eax,RAND_MAX
    cvtsi2ss xmm1,eax
    shufps xmm1,xmm1,0x00
    divps xmm0,xmm1
}
;-------------------------------------------------------------------------------
; Vector4
;-------------------------------------------------------------------------------
struc Vector4 {
    .x dd ?
    .y dd ?
    .z dd ?
    .w dd ?
}
virtual at 0
    Vector4 Vector4
    sizeof.Vector4 = $
end virtual
;-------------------------------------------------------------------------------
; Matrix4
;-------------------------------------------------------------------------------
struc Matrix4 {
    .c0 Vector4
    .c1 Vector4
    .c2 Vector4
    .c3 Vector4
}
virtual at 0
    Matrix4 Matrix4
    sizeof.Matrix4 = $
end virtual
;-------------------------------------------------------------------------------
; Atom
;-------------------------------------------------------------------------------
struc Atom {
    .pos Vector4
    .vel Vector4
    .accel Vector4
    .force Vector4
    .mass Vector4
    .radius Vector4
    .rotation Matrix4
}
virtual at 0
    Atom Atom
    sizeof.Atom = $
end virtual
;-------------------------------------------------------------------------------
align 16
atom_new:
    push rbx rbp
    sub rsp,8
    mov rbp,rsp
    sub rsp,128
    m0 equ rbp-sizeof.Matrix4
    m1 equ rbp-2*sizeof.Matrix4
    mov rbx,rdi
    virtual at rbx
        .this Atom
    end virtual
    ; compute velocity
    rand_v3_f32
    addps xmm0,dqword [am_v4_f32_0p5]
    vm_v4_set1 xmm1,10.0
    mulps xmm0,xmm1
    movaps [.this.vel],xmm0
    ; compute position
    rand_v3_f32
    addps xmm0,dqword [am_v4_f32_0p5]
    vm_v4_set1 xmm1,20.0
    mulps xmm0,xmm1
    movaps [.this.pos],xmm0
    ; compute mass
    rand_f32
    addss xmm0,xmm0
    shufps xmm0,xmm0,0x00
    movaps [.this.mass],xmm0
    ; compute radius
    vm_s_set xmm1,15.0
    mulss xmm0,xmm1
    movss xmm1,[am_v4_f32_2pi]
    addss xmm1,xmm1
    emit am_pow_ss,<divss xmm0,xmm1>,<vm_s_set xmm1,0.3333>
    shufps xmm0,xmm0,0x00
    movaps [.this.radius],xmm0
    ; compute rotation
    emit vm_m4_rotation_x m0,<rand_f32>,<mulss xmm0,[am_v4_f32_pi]>
    emit vm_m4_rotation_z m1,<rand_f32>,<mulss xmm0,[am_v4_f32_pi]>
    vm_m4_mul_m4 .this.rotation,m0,m1
    ; clear
    xorps xmm0,xmm0
    movaps [.this.accel],xmm0
    movaps [.this.force],xmm0
    restore m
    mov rsp,rbp
    add rsp,8
    pop rbp rbx
    ret
;-------------------------------------------------------------------------------
; in: rdi - this pointer
; in: esi - atoms count
; in: rdx - atoms pointer
align 16
atom_compute_force:
    push rbp
    mov rbp,rsp
    sub rsp,32
    i equ rbp-4
    atoms_count equ rbp-8
    mov [atoms_count],esi
    virtual at rdi
        .this Atom
    end virtual
    virtual at rdx
        .atom Atom
    end virtual
    mov dword [i],0
      .for_each_atom:
    mov eax,[i]
    cmp eax,[atoms_count]
    jge .for_each_atom_end
    cmp rdi,rdx
    je .for_each_atom_inc
    movaps xmm0,[.this.pos]
    subps xmm0,[.atom.pos]
    movaps xmm7,xmm0
    vm_v3_length
    mulss xmm0,xmm0
    movss xmm1,xmm0
    vm_s_set xmm2,0.001
    mulss xmm1,xmm2
    addss xmm0,[am_v4_f32_1]
    vm_s_set xmm2,-20.0
    divss xmm2,xmm0
    addss xmm2,xmm1
    movss xmm0,[.this.mass]
    mulss xmm0,xmm2
    mulss xmm0,[.atom.mass]
    movss xmm6,xmm0
    shufps xmm6,xmm6,0x00
    emit vm_v3_normalize,<movaps xmm0,xmm7>
    mulps xmm0,xmm6
    movaps xmm1,[.this.force]
    addps xmm1,xmm0
    movaps [.this.force],xmm1
    movaps xmm1,[.atom.force]
    subps xmm1,xmm0
    movaps [.atom.force],xmm1
      .for_each_atom_inc:
    add dword [i],1
    add rdx,sizeof.Atom
    jmp .for_each_atom
      .for_each_atom_end:
    restore i,atoms_count
    mov rsp,rbp
    pop rbp
    ret
;-------------------------------------------------------------------------------
; in: rdi - this pointer
; in: esi - time step
align 16
atom_integrate:
    sub rsp,8
    virtual at rdi
        .this Atom
    end virtual
    movaps xmm0,[.this.force]
    mulps xmm0,dqword [am_v4_f32_0p5]
    divps xmm0,[.this.mass]
    movaps [.this.accel],xmm0
    movd xmm1,esi
    shufps xmm1,xmm1,0x00
    mulps xmm0,xmm1
    movaps xmm3,[.this.vel]
    addps xmm3,xmm0
    movaps [.this.vel],xmm3
    mulps xmm3,xmm1
    movaps xmm2,[.this.pos] 
    addps xmm2,xmm3
    movaps [.this.pos],xmm2
    xorps xmm0,xmm0
    movaps [.this.force],xmm0
    add rsp,8
    ret
;-------------------------------------------------------------------------------
; Mesh
;-------------------------------------------------------------------------------
struc Mesh {
    .buffer_vertex dd ?
    .buffer_normal dd ?
    .buffer_texcoord dd ?
    .buffer_index dd ?
    .buffer_vertex_addr dq ?
    .buffer_normal_addr dq ?
    .buffer_texcoord_addr dq ?
    .buffer_index_addr dq ?
    .buffer_vertex_size dd ?
    .buffer_normal_size dd ?
    .buffer_texcoord_size dd ?
    .buffer_index_size dd ?
    .index_count dd ?
    .vertex_count dd ?
}
virtual at 0
    Mesh Mesh
    sizeof.Mesh = $
end virtual
;-------------------------------------------------------------------------------
align 16
mesh_new:
    virtual at rdi
        .this Mesh
    end virtual
    mov [.this.buffer_vertex],0
    mov [.this.buffer_normal],0
    mov [.this.buffer_texcoord],0
    mov [.this.buffer_index],0
    mov [.this.buffer_vertex_addr],0
    mov [.this.buffer_normal_addr],0
    mov [.this.buffer_texcoord_addr],0
    mov [.this.buffer_index_addr],0
    mov [.this.buffer_vertex_size],0
    mov [.this.buffer_normal_size],0
    mov [.this.buffer_texcoord_size],0
    mov [.this.buffer_index_size],0
    mov [.this.index_count],0
    mov [.this.vertex_count],0
    ret
;-------------------------------------------------------------------------------
align 16
mesh_load:
    push rbx rbp
    sub rsp,8
    mov rbp,rsp
    sub rsp,64
    ctm_ctx equ rbp-16
    ptr_vertices equ rbp-32
    ptr_normals equ rbp-40
    ptr_texcoords equ rbp-48
    ptr_indices equ rbp-56
    filename equ rbp-64
    mov rbx,rdi
    virtual at rbx
        .this Mesh
    end virtual
    mov [filename],rsi
    ; create ctm context
    call [ctmNewContext],<mov edi,CTM_IMPORT>
    mov [ctm_ctx],rax
    ; load mesh
    call [ctmLoad],<mov rdi,[ctm_ctx]>,<mov rsi,[filename]>
    ; get vertex count and compute attrib buffer sizes
    call [ctmGetInteger],<mov rdi,[ctm_ctx]>,<mov esi,CTM_VERTEX_COUNT>
    mov [.this.vertex_count],eax
    imul eax,[.this.vertex_count],12
    mov [.this.buffer_vertex_size],eax
    mov [.this.buffer_normal_size],eax
    imul eax,[.this.vertex_count],8
    mov [.this.buffer_texcoord_size],eax
    ; get triangle count and compute index buffer size
    call [ctmGetInteger],<mov rdi,[ctm_ctx]>,<mov esi,CTM_TRIANGLE_COUNT>
    imul eax,eax,3
    mov [.this.index_count],eax
    imul eax,[.this.index_count],4
    mov [.this.buffer_index_size],eax
    ; get vertex array
    call [ctmGetFloatArray],<mov rdi,[ctm_ctx]>,<mov esi,CTM_VERTICES>
    mov [ptr_vertices],rax
    ; get normal array
    call [ctmGetFloatArray],<mov rdi,[ctm_ctx]>,<mov esi,CTM_NORMALS>
    mov [ptr_normals],rax
    ; get texcoord array
    call [ctmGetFloatArray],<mov rdi,[ctm_ctx]>,<mov esi,CTM_UV_MAP_1>
    mov [ptr_texcoords],rax
    ; get index array
    call [ctmGetIntegerArray],<mov rdi,[ctm_ctx]>,<mov esi,CTM_INDICES>
    mov [ptr_indices],rax
    ; gen buffers
    call [glGenBuffers],<mov edi,4>,<lea rsi,[.this.buffer_vertex]>
    ; vertex buffer
    call [glNamedBufferDataEXT],<mov edi,[.this.buffer_vertex]>,<mov esi,[.this.buffer_vertex_size]>,<mov rdx,[ptr_vertices]>,<mov ecx,GL_STATIC_DRAW>
    call [glGetNamedBufferParameterui64vNV],<mov edi,[.this.buffer_vertex]>,<mov esi,GL_BUFFER_GPU_ADDRESS_NV>,<lea rdx,[.this.buffer_vertex_addr]>
    call [glMakeNamedBufferResidentNV],<mov edi,[.this.buffer_vertex]>,<mov esi,GL_READ_ONLY>
    ; normal buffer
    call [glNamedBufferDataEXT],<mov edi,[.this.buffer_normal]>,<mov esi,[.this.buffer_normal_size]>,<mov rdx,[ptr_normals]>,<mov ecx,GL_STATIC_DRAW>
    call [glGetNamedBufferParameterui64vNV],<mov edi,[.this.buffer_normal]>,<mov esi,GL_BUFFER_GPU_ADDRESS_NV>,<lea rdx,[.this.buffer_normal_addr]>
    call [glMakeNamedBufferResidentNV],<mov edi,[.this.buffer_normal]>,<mov esi,GL_READ_ONLY>
    ; texcoord buffer
    call [glNamedBufferDataEXT],<mov edi,[.this.buffer_texcoord]>,<mov esi,[.this.buffer_texcoord_size]>,<mov rdx,[ptr_texcoords]>,<mov ecx,GL_STATIC_DRAW>
    call [glGetNamedBufferParameterui64vNV],<mov edi,[.this.buffer_texcoord]>,<mov esi,GL_BUFFER_GPU_ADDRESS_NV>,<lea rdx,[.this.buffer_texcoord_addr]>
    call [glMakeNamedBufferResidentNV],<mov edi,[.this.buffer_texcoord]>,<mov esi,GL_READ_ONLY>
    ; index buffer
    call [glNamedBufferDataEXT],<mov edi,[.this.buffer_index]>,<mov esi,[.this.buffer_index_size]>,<mov rdx,[ptr_indices]>,<mov ecx,GL_STATIC_DRAW>
    call [glGetNamedBufferParameterui64vNV],<mov edi,[.this.buffer_index]>,<mov esi,GL_BUFFER_GPU_ADDRESS_NV>,<lea rdx,[.this.buffer_index_addr]>
    call [glMakeNamedBufferResidentNV],<mov edi,[.this.buffer_index]>,<mov esi,GL_READ_ONLY>
    ; free ctm context
    call [ctmFreeContext],<mov edi,[ctm_ctx]>
    restore ctm_ctx,ptr_vertices,ptr_normals,ptr_texcoords,ptr_indices
    mov rsp,rbp
    add rsp,8
    pop rbp rbx
    ret
;-------------------------------------------------------------------------------
align 16
mesh_draw:
    push rbx
    mov rbx,rdi
    virtual at rbx
        .this Mesh
    end virtual
    ; set buffers
    call [glBufferAddressRangeNV],\
        <mov edi,GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV>,<mov esi,0>,<mov rdx,[.this.buffer_vertex_addr]>,<mov ecx,[.this.buffer_vertex_size]>
    call [glBufferAddressRangeNV],\
        <mov edi,GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV>,<mov esi,1>,<mov rdx,[.this.buffer_normal_addr]>,<mov ecx,[.this.buffer_normal_size]>
    call [glBufferAddressRangeNV],\
        <mov edi,GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV>,<mov esi,2>,<mov rdx,[.this.buffer_texcoord_addr]>,<mov ecx,[.this.buffer_texcoord_size]>
    call [glBufferAddressRangeNV],\
        <mov edi,GL_ELEMENT_ARRAY_ADDRESS_NV>,<mov esi,0>,<mov rdx,[.this.buffer_index_addr]>,<mov ecx,[.this.buffer_index_size]>
    ; draw
    call [glDrawElements],<mov edi,GL_TRIANGLES>,<mov esi,[.this.index_count]>,<mov edx,GL_UNSIGNED_INT>,<mov ecx,0>
    pop rbx
    ret
;-------------------------------------------------------------------------------
; name: create_texture
;
align 16
create_texture:
    push rbp
    mov rbp,rsp
    sub rsp,32
    w equ rbp-4
    h equ rbp-8
    c equ rbp-12
    pixels equ rbp-24
    ; load image
    call [stbi_load],<lea rdi,[n_str_texture]>,<lea rsi,[w]>,<lea rdx,[h]>,<lea rcx,[c]>,<mov r8d,STBI_rgb>
    mov [pixels],rax
    ; gen texture name
    call [glGenTextures],<mov edi,1>,<lea rsi,[n_texture]>
    ; set texture parameters
    call [glTextureParameteriEXT],<mov edi,[n_texture]>,<mov esi,GL_TEXTURE_2D>,<mov edx,GL_TEXTURE_MAG_FILTER>,<mov ecx,GL_LINEAR>
    call [glTextureParameteriEXT],<mov edi,[n_texture]>,<mov esi,GL_TEXTURE_2D>,<mov edx,GL_TEXTURE_MIN_FILTER>,<mov ecx,GL_LINEAR>
    call [glTextureParameteriEXT],<mov edi,[n_texture]>,<mov esi,GL_TEXTURE_2D>,<mov edx,GL_TEXTURE_WRAP_S>,<mov ecx,GL_CLAMP_TO_EDGE>
    call [glTextureParameteriEXT],<mov edi,[n_texture]>,<mov esi,GL_TEXTURE_2D>,<mov edx,GL_TEXTURE_WRAP_T>,<mov ecx,GL_CLAMP_TO_EDGE>
    ; upload texture image
    call [glTextureImage2DEXT],\
        <mov edi,[n_texture]>,<mov esi,GL_TEXTURE_2D>,<mov edx,0>,<mov ecx,GL_RGB8>,<mov r8d,[w]>,<mov r9d,[h]>,\
        <push qword [pixels]>,<push GL_UNSIGNED_BYTE>,<push GL_RGB>,<push 0>
    add rsp,32
    ; free pixel data
    call [stbi_image_free],<mov rdi,[pixels]>
    restore w,h,c,pixels
    mov rsp,rbp
    pop rbp
    ret
;-------------------------------------------------------------------------------
; name: update_atoms
;
align 16
update_atoms:
    push rbx rbp
    sub rsp,8
    mov rbp,rsp
    sub rsp,32
    i equ rbp-4
    center equ rbp-32
    mov rbx,[n_atoms]
    virtual at rbx
        .atom Atom
    end virtual
    mov dword [i],0
    xorps xmm0,xmm0
    movaps [center],xmm0
      .for_each_atom:
    movaps xmm0,dqword [center]
    addps xmm0,[.atom.pos]
    movaps [center],xmm0
    call atom_integrate,<mov rdi,rbx>,<mov esi,0.0001>
    add rbx,sizeof.Atom
    add dword [i],1
    cmp dword [i],ATOMS_COUNT
    jne .for_each_atom
    mov dword [i],0
    mov rbx,[n_atoms]
      .for_each_atom2:
    call atom_compute_force,<mov rdi,rbx>,<mov esi,ATOMS_COUNT>,<mov rdx,[n_atoms]>
    add rbx,sizeof.Atom
    add dword [i],1
    cmp dword [i],ATOMS_COUNT
    jne .for_each_atom2
    ; calculate the center
    mov eax,ATOMS_COUNT
    cvtsi2ss xmm1,eax
    shufps xmm1,xmm1,0x00
    movaps xmm0,dqword [center]
    divps xmm0,xmm1
    restore i,center
    mov rsp,rbp
    add rsp,8
    pop rbp rbx
    ret
;-------------------------------------------------------------------------------
; name: draw_atoms
;
align 16
draw_atoms:
    push rbx rbp
    sub rsp,8
    mov rbp,rsp
    sub rsp,256
    m0 equ rbp-sizeof.Matrix4
    m1 equ rbp-2*sizeof.Matrix4
    mv_ptr equ rbp-2*sizeof.Matrix4-8
    i equ rbp-2*sizeof.Matrix4-8-4
    mov [mv_ptr],rdi
    mov rbx,[n_atoms]
    virtual at rbx
        .atom Atom
    end virtual
    mov dword [i],0
      .for_each_atom:
    ; set matrix
    movaps xmm0,[.atom.pos]
    vm_m4_translation m0
    movaps xmm0,[.atom.radius]
    vm_m4_scale m1
    vm_m4_mul_m4 m0,m0,m1
    vm_m4_mul_m4 m0,m0,.atom.rotation
    mov rsi,[mv_ptr]
    vm_m4_mul_m4 m1,rsi,m0
    vm_m4_transpose m1,m1
    call [glNamedProgramLocalParameters4fvEXT],<mov edi,[n_program+0]>,<mov esi,GL_VERTEX_PROGRAM_ARB>,<mov edx,0>,<mov ecx,4>,<lea r8,[m1]>
    call mesh_draw,<mov rdi,[n_mesh]>
    ; move to the next atom
    add rbx,sizeof.Atom
    add dword [i],1
    cmp dword [i],ATOMS_COUNT
    jne .for_each_atom 
    restore m0,m1,mv_ptr,i
    mov rsp,rbp
    add rsp,8
    pop rbp rbx
    ret
;-------------------------------------------------------------------------------
; name: init
;
align 16
init:
    push rbx rbp
    sub rsp,8
    mov rbp,rsp
    sub rsp,16
    i equ rbp-4
    ; init libraries
    call openctm_init
    call stb_image_init
    ; init random generator
    call [time],<mov edi,0>
    call [srand],<mov edi,eax>
    ; create atoms
    call [malloc],<mov edi,sizeof.Atom * ATOMS_COUNT>
    mov [n_atoms],rax
    mov rbx,rax
    mov dword [i],0
      .for_each_atom:
    call atom_new,<mov rdi,rbx>
    add rbx,sizeof.Atom
    add dword [i],1
    cmp dword [i],ATOMS_COUNT
    jne .for_each_atom
    ; create and load texture
    call create_texture
    ; allocate memory for the mesh object
    call [malloc],<mov edi,sizeof.Mesh>
    mov [n_mesh],rax
    ; create and load mesh
    call mesh_new,<mov rdi,[n_mesh]>
    call mesh_load,<mov rdi,[n_mesh]>,<mov rsi,n_str_mesh>
    ; gen programs
    call [glGenProgramsARB],<mov edi,2>,<lea rsi,[n_program]>
    ; vertex program
    call [glNamedProgramStringEXT],\
        <mov edi,[n_program+0]>,<mov esi,GL_VERTEX_PROGRAM_ARB>,<mov edx,GL_PROGRAM_FORMAT_ASCII_ARB>,<mov ecx,[n_src_vp_len]>,<mov r8,n_src_vp>
    ; fragment program
    call [glNamedProgramStringEXT],\
        <mov edi,[n_program+4]>,<mov esi,GL_FRAGMENT_PROGRAM_ARB>,<mov edx,GL_PROGRAM_FORMAT_ASCII_ARB>,<mov ecx,[n_src_fp_len]>,<mov r8,n_src_fp>
    ; setup GL state
    call [glEnable],<mov edi,GL_VERTEX_PROGRAM_ARB>
    call [glEnable],<mov edi,GL_FRAGMENT_PROGRAM_ARB>
    call [glEnable],<mov edi,GL_DEPTH_TEST>
    ; check for GL errors
    call [glGetError]
    call [printf],<mov rdi,n_str_print_d>,<mov rsi,rax>
    restore i
    mov rsp,rbp
    add rsp,8
    pop rbp rbx
    ret
;-------------------------------------------------------------------------------
; name: update
;
align 16
update:
    push rbp
    mov rbp,rsp
    sub rsp,128
    m equ rbp-sizeof.Matrix4
    mv equ rbp-2*sizeof.Matrix4
    ; update atoms
    call update_atoms
    movaps xmm1,xmm0
    ; compute view matrix
    vm_v3_set xmm0,0.0,0.0,100.0
    ;vm_v3_set xmm1,0.0,0.0,0.0
    vm_v3_set xmm2,0.0,1.0,0.0
    vm_m4_lookat m
    ; compute projection matrix
    emit vm_m4_perspective mv,<vm_s_set xmm0,0.785398163>,<vm_s_set xmm1,1.6>,<vm_s_set xmm2,0.1>,<vm_s_set xmm3,200.0>
    ; compute mvp matrix
    vm_m4_mul_m4 mv,mv,m
    ; clear
    call [glClear],<mov edi,GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT>
    ; enable vertex arrays
    call [glEnableClientState],<mov edi,GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV>
    call [glEnableClientState],<mov edi,GL_ELEMENT_ARRAY_UNIFIED_NV>
    call [glEnableVertexAttribArray],<mov edi,0>
    call [glEnableVertexAttribArray],<mov edi,1>
    call [glEnableVertexAttribArray],<mov edi,2>
    ; set vertex array format
    call [glVertexAttribFormatNV],<mov edi,0>,<mov esi,3>,<mov edx,GL_FLOAT>,<mov ecx,GL_FALSE>,<mov r8d,0>
    call [glVertexAttribFormatNV],<mov edi,1>,<mov esi,3>,<mov edx,GL_FLOAT>,<mov ecx,GL_FALSE>,<mov r8d,0>
    call [glVertexAttribFormatNV],<mov edi,2>,<mov esi,2>,<mov edx,GL_FLOAT>,<mov ecx,GL_FALSE>,<mov r8d,0>
    ; bind programs
    call [glBindProgramARB],<mov edi,GL_VERTEX_PROGRAM_ARB>,<mov esi,[n_program+0]>
    call [glBindProgramARB],<mov edi,GL_FRAGMENT_PROGRAM_ARB>,<mov esi,[n_program+4]>
    ; bind texture
    call [glBindMultiTextureEXT],<mov edi,GL_TEXTURE0>,<mov esi,GL_TEXTURE_2D>,<mov edx,[n_texture]>
    ; draw atoms
    call draw_atoms,<lea rdi,[mv]>
    restore m,mv
    mov rsp,rbp
    pop rbp
    ret
;-------------------------------------------------------------------------------
; name: quit
;
align 16
quit:
    sub rsp,8
    call window_close
    add rsp,8
    ret
;-------------------------------------------------------------------------------
; name: main
;
align 16
main:
    sub rsp,8
    call window_open,<mov edi,10>,<mov esi,10>,<mov edx,1440>,<mov ecx,900>
    ; init demo
    call init
    ; enter main loop
      .main_loop:
    ; get time
    call [clock],<mov edi,0>
    cvtsi2ss xmm0,eax
    mov eax,CLOCKS_PER_SEC
    cvtsi2ss xmm1,eax
    divss xmm0,xmm1
    movss [n_time],xmm0
    ; update demo
    call update
    ; swap buffers
    call window_swap
    test eax,eax
    jnz .finish
    jmp .main_loop
      .finish:
    add rsp,8
    ret
;-------------------------------------------------------------------------------
; name: start
;
align 16
start:
    call main
    ; terminate process
    call [exit],<mov edi,0>
;-------------------------------------------------------------------------------

segment readable writeable

ENEIDA_UTIL_INCLUDE = 'DATA'
include 'util/util_amath.inc'
include 'util/util_vmath.inc'
include 'util/util_window.inc'
include 'util/util_openctm.inc'
include 'util/util_stb_image.inc'

align 8

n_mesh dq 0
n_program dd 0,0
n_time dd 0
n_texture dd 0

align 8
n_atoms dq 0
ATOMS_COUNT = 30

NL equ db 10,

n_src_vp db '!!NVvp4.0'
NL 'FLOAT PARAM rot[4] = { program.local[0..3] };'
NL 'main:'
NL '    DP4.F result.position.x, rot[0], vertex.attrib[0];'
NL '    DP4.F result.position.y, rot[1], vertex.attrib[0];'
NL '    DP4.F result.position.z, rot[2], vertex.attrib[0];'
NL '    DP4.F result.position.w, rot[3], vertex.attrib[0];'
NL '    MOV.F result.attrib[0], vertex.attrib[1];'
NL '    MOV.F result.attrib[1], vertex.attrib[2];'
NL '    RET;'
NL 'END',0
n_src_vp_len dd $-n_src_vp-1
n_src_fp db '!!NVfp4.0'
NL 'main:'
NL '    TEX result.color, fragment.attrib[1], texture[0], 2D;'
NL '    RET;'
NL 'END',0
n_src_fp_len dd $-n_src_fp-1

n_str_print_p db '%p',10,0
n_str_print_d db '%d',10,0
n_str_print_f db '%f',10,0
n_str_mesh db './data/mesh.ctm',0
n_str_texture db './data/mesh.jpg',0

;-------------------------------------------------------------------------------
